package gw.com.android.ui.record;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.gwtsz.gts2.hx.R;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import butterknife.BindView;
import butterknife.OnClick;
import gw.com.android.app.AppContances;
import gw.com.android.app.AppMain;
import gw.com.android.app.GTConfig;
import gw.com.android.presenter.http.Https;
import gw.com.android.ui.BaseActivity;
import okhttp3.Request;
import okhttp3.Response;
import www.com.library.app.Logger;
import www.com.library.util.NetworkMonitor;
import www.com.library.util.PermissionUtil;

/**
 * @author jett
 * @since 2018-03-01.
 */
public class RecordActivity extends BaseActivity implements SurfaceHolder.Callback {

    private final String TAG = "RecordActivity";

    private static final int VIDEO_WIDTH = 640;
    private static final int VIDEO_HEIGHT = 480;
    private static final int STATE_NONE = 0;
    private static final int STATE_PREPARE = 1;
    private static final int STATE_RECORDING = 2;

    @BindView(R.id.camera_preview)
    SurfaceView mPreview;
    @BindView(R.id.record_start)
    TextView tvStart;
    @BindView(R.id.record_bg)
    ImageView ivRecordBg;
    @BindView(R.id.record_timer_container)
    ViewGroup timerContainer;
    @BindView(R.id.record_time)
    TextView tvTime;
    @BindView(R.id.record_count)
    TextView tvTimeTotal;
    @BindView(R.id.record_description1)
    TextView tvDesc1;
    @BindView(R.id.record_description2)
    TextView tvDesc2;
    @BindView(R.id.record_description3)
    TextView tvDesc3;
    @BindView(R.id.record_description4)
    TextView tvDesc4;
    @BindView(R.id.finish_layout)
    View finishLayout;

    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;
    private MediaRecorder mRecorder;
    private File mVideoFile;
    private int recordTime;
    private int state = STATE_NONE;
    private RecordLoading recordLoading;
    private int currentProgress = 0;

    private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    protected int getLayoutView() {
        return R.layout.activity_record;
    }

    @Override
    protected void initLayoutView() {
        mTitleBar.setAppTitle(AppMain.getAppString(R.string.record_title));

        mSurfaceHolder = mPreview.getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
        mSurfaceHolder.addCallback(this);
        // setType必须设置，要不出错.
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    protected void initViewData() {
    }

    @OnClick(R.id.record_start)
    void startRecord(View view) {
        if (state == STATE_PREPARE) {
            return;
        }
        if (state == STATE_RECORDING) {
            stopMediaRecord();
            onRecordCompleted();
        } else {
            start();
        }
    }

    @OnClick(R.id.reset_btn)
    void resetRecord(View view) {
        stopMediaRecord();
        onRecordReset();
        deleteVideoFile();
    }

    @OnClick(R.id.upload_btn)
    void uploadRecord(View view) {
        if (!NetworkMonitor.hasNetWork()) {
            return;
        }
        recordLoading = new RecordLoading(this);
        recordLoading.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {

            }
        });
        currentProgress = 0;
        recordLoading.setProgress(currentProgress);
        recordLoading.show();

        String url = "https://localhost/null";
        new Https(url).addUploadFile("name", null, mVideoFile).upload(new Https.UploadListener() {
            @Override
            public void onUploading(long current, long total, boolean done) {
                int precent = (int) (current * 100 / total);
                recordLoading.setProgress(precent);
            }

            @Override
            public void onSuccess(Request request, Response response, Object result, int code) {
                Logger.e(TAG, "upload video success");
                recordLoading.dismiss();
                toResult();
                deleteVideoFile();
            }

            @Override
            public void onFailure(Request request, IOException e) {
                Logger.e(TAG, "upload video failed");
                recordLoading.dismiss();
                showToastPopWindow(getString(R.string.record_upload_failure));
                deleteVideoFile();
            }
        });
    }

    private void toResult() {
        startActivity(new Intent(this, RecordResultActivity.class));
    }

    private void deleteVideoFile() {
        if (mVideoFile != null && mVideoFile.exists()) {
            boolean delete = mVideoFile.delete();
            Logger.i(TAG, "delete video file result = " + delete);
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (state != STATE_NONE) {
            stopMediaRecord();
            onRecordCompleted();
        }
    }

    private void start() {
        state = STATE_PREPARE;
        requestCameraPermission();
    }

    PermissionUtil mCameraPermission = new PermissionUtil();
    PermissionUtil mAudioPermission2 = new PermissionUtil();

    /**
     * 获取拍照需要的权限
     */
    private void requestCameraPermission() {
        mCameraPermission.requestPermission(this, Manifest.permission.CAMERA, AppContances.REQUEST_PERMISSION_ACCESS_CAMERA, new PermissionUtil.OnRequestPermissionResult() {
            @Override
            public void onGranted() {
                if (ActivityCompat.checkSelfPermission(RecordActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                    requestRecordPermission();
                } else {
                    Logger.i(TAG, "request camera permission has refused .. ");
                }
            }

            @Override
            public void onRefused() {
                Logger.i(TAG, "request camera permission has refused");
            }
        });
    }

    /**
     * 获取录视频需要的权限
     */
    private void requestRecordPermission() {
        mAudioPermission2.requestPermission(this, Manifest.permission.RECORD_AUDIO, AppContances.REQUEST_PERMISSION_ACCESS_RECORD, new PermissionUtil.OnRequestPermissionResult() {
            @Override
            public void onGranted() {
                if (ActivityCompat.checkSelfPermission(RecordActivity.this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
                    startMediaRecord();
                } else {
                    Logger.i(TAG, "request record audio permission has refused .. ");
                }
            }

            @Override
            public void onRefused() {
                Logger.i(TAG, "request record audio permission has refused");
            }
        });
    }

    private boolean tryOpenCamera() {
        try {
            int mCameraId = RecordHelper.acquireCameraId();
            mCamera = Camera.open(mCameraId);
            return mCamera != null;
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return false;
    }

    private void startMediaRecord() {
        Logger.i(TAG, "startMediaRecord");
        if (!tryOpenCamera()) {
            Logger.i(TAG, "try to open camera failed...");
            state = STATE_NONE;
            return;
        }
        if (mCamera == null) {
            Logger.i(TAG, "mCamera is null");
            state = STATE_NONE;
            return;
        }
        int mCameraId = RecordHelper.acquireCameraId();
        mCamera.setDisplayOrientation(RecordHelper.getCameraDisplayOrientation(this, mCameraId));
        try {
            if (mRecorder == null) {
                mRecorder = new MediaRecorder();
            }
            mCamera.unlock();
            mRecorder.setCamera(mCamera);

            // 这两项需要放在setOutputFormat之前
            mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            // Set output file format
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            // 这两项需要放在setOutputFormat之后
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
            mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);

            mRecorder.setOrientationHint(RecordHelper.getOrientationHint(this, mCameraId));
            //设置录制视频尺寸，部分手机获取不到getParameters，导致错误
            //Camera.Parameters parameters = mCamera.getParameters();
            //Camera.Size optimalSize = RecordHelper.getOptimalSize(parameters.getSupportedVideoSizes(), VIDEO_WIDTH, VIDEO_HEIGHT);
            //parameters.setPreviewSize(optimalSize.width, optimalSize.height);
            mRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
            //设置录制的视频帧率，视频的帧率和视频大小是需要硬件支持的，如果设置的帧率和视频大小,如果硬件不支持就会出现错误。
            //mRecorder.setVideoFrameRate(30);
            mRecorder.setVideoEncodingBitRate(512 * 1024);
            //设置记录会话的最大持续时间（毫秒）,前置的无效，后置的有效
            //mRecorder.setMaxDuration(5 * 1000);
            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());

            mVideoFile = getVideoFile();
            mRecorder.setOutputFile(mVideoFile.getPath());
            mRecorder.prepare();
            mRecorder.start();
            onRecordStarted();
            state = STATE_RECORDING;
            Logger.i(TAG, "recording...");
        } catch (Exception e) {
            Logger.e(TAG, e);
            state = STATE_NONE;
        }
    }

    private void stopMediaRecord() {
        Logger.i(TAG, "stopMediaRecord");
        try {
            if (mRecorder != null) {
                mRecorder.stop();
                mRecorder.reset();
                mRecorder.release();
                mRecorder = null;
            }
        } catch (Exception e) {
            Logger.e(TAG, e);
        } finally {
            mRecorder = null;
        }
        try {
            if (mCamera != null) {
                mCamera.release();
            }
        } catch (RuntimeException ignore) {
        } finally {
            mCamera = null;
        }
        state = STATE_NONE;
    }

    private void onRecordReset() {
        recordTime = 0;
        ivRecordBg.setVisibility(View.VISIBLE);
        timerContainer.setVisibility(View.GONE);
        tvDesc1.setVisibility(View.VISIBLE);
        tvDesc2.setVisibility(View.VISIBLE);
        tvDesc3.setVisibility(View.GONE);
        tvDesc4.setVisibility(View.GONE);
        tvTimeTotal.setVisibility(View.GONE);
        tvTime.setText("");
        tvStart.setText(R.string.record_start);
        tvStart.setVisibility(View.VISIBLE);
        finishLayout.setVisibility(View.GONE);
    }

    private void onRecordStarted() {
        recordTime = 0;
        handler.postDelayed(runnable, 1000);
        ivRecordBg.setVisibility(View.GONE);
        timerContainer.setVisibility(View.VISIBLE);
        tvDesc1.setVisibility(View.GONE);
        tvDesc2.setVisibility(View.GONE);
        tvDesc3.setVisibility(View.VISIBLE);
        tvDesc4.setVisibility(View.VISIBLE);
        tvTimeTotal.setVisibility(View.GONE);
        tvTime.setText(buildRecordTimeString());
        tvStart.setText(R.string.record_complete);
        tvStart.setVisibility(View.VISIBLE);
        finishLayout.setVisibility(View.GONE);
    }

    private void onRecordCompleted() {
        handler.removeCallbacks(runnable);
        timerContainer.setVisibility(View.GONE);
        tvTimeTotal.setVisibility(View.VISIBLE);
        tvTimeTotal.setText(buildRecordTimeString());
        tvStart.setVisibility(View.GONE);
        finishLayout.setVisibility(View.VISIBLE);
    }

    private String buildRecordTimeString() {
        int minute = recordTime / 60;
        int second = recordTime % 60;
        StringBuilder sb = new StringBuilder();
        sb.append("00:");
        if (minute < 10) {
            sb.append("0");
        }
        sb.append(minute).append(":");
        if (second < 10) {
            sb.append("0");
        }
        sb.append(second);
        return sb.toString();
    }

    private File getVideoFile() {
        String cacheDir = GTConfig.instance().getRootDirectory() + "/VideoFile";
        File file = new File(cacheDir);
        if (!file.exists()) {
            file.mkdirs();
        }
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(new Date());
        String name = "record_" + timestamp + ".mp4";
        return new File(cacheDir, name);
    }

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            recordTime++;
            if (recordTime >= 40) {
                recordTime = 40;
                tvTime.setText(buildRecordTimeString());
                stopMediaRecord();
                onRecordCompleted();
            } else {
                handler.postDelayed(this, 1000);
            }
            tvTime.setText(buildRecordTimeString());
        }
    };

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (null != mCameraPermission && requestCode == AppContances.REQUEST_PERMISSION_ACCESS_CAMERA) {
            mCameraPermission.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
        if (null != mAudioPermission2 && requestCode == AppContances.REQUEST_PERMISSION_ACCESS_RECORD) {
            mAudioPermission2.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    @Override
    protected void onDestroy() {
        if (state != STATE_NONE) {
            stopMediaRecord();
        }
        super.onDestroy();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }

}
